package com.core.shared;

import org.apache.lucene.store.RandomAccessInput;
import sun.misc.Cleaner;

import java.io.*;
import java.lang.reflect.Method;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: xianfei
 * Date: 2016-01-21
 * Time: 11:55
 * To change this template use Editor | File and Code Templates.
 */
public class NIOHandle {

    public static void main(String[] args) throws InterruptedException {
//        CharBuffer buffer = CharBuffer.allocate(8);
//        System.out.println("capacity:" + buffer.capacity());
//        System.out.println("limit:" + buffer.limit());
//        System.out.println("position:" + buffer.position());
//        buffer.put("a");
//        buffer.put("b");
//        buffer.put("c");
//        System.out.println("put后position:" + buffer.position());
//        buffer.flip();
//        System.out.println("flip后limit:" + buffer.limit());
//        System.out.println("flip后position:" + buffer.position());
//        System.out.println("第一个元素：" + buffer.get());
//        System.out.println("取出第一个元素后position:" + buffer.position());
//        buffer.clear();
//        System.out.println("clear后limit:" + buffer.limit());
//        System.out.println("clear后position:" + buffer.position());
//        System.out.println("第二个元素,缓冲区内容没有清除：" + buffer.get(1));
        Thread.sleep(10000);
        System.out.println("---start ---");
        m1();
    }

    //47882ms

    /**
     * 1.2G，zip文件，1kb复制，47882ms
     * 1.2G，zip文件，1mb复制，22227ms
     * 1.2G，zip文件，10mb复制，14430ms
     * 分配的直接内存受限于 -XX:MaxDirectMemorySize=100M，如果为配置此参数，则与-Xmx相同
     */
    public static void m1() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {
            long start = System.currentTimeMillis();
            RandomAccessFile rFile = new RandomAccessFile("D:\\setupbag\\eclipse-jee-lune.zip", "r");
            RandomAccessFile wFile = new RandomAccessFile("D:\\setupbag\\eclipse-jee-lune2.zip", "rw");
            inChannel = rFile.getChannel();
            outChannel = wFile.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024 * 10);
            int index = 0;
            while (index != -1) {
                buffer.clear(); // position=0,limit=最大inChannel
                index = inChannel.read(buffer);   //在inChannel读取buffer大小数据到buffer
                buffer.flip();   // position=0,limit=当前inChannel读取位置
                outChannel.write(buffer);   //outChannel写入buffer中的数据
            }
            inChannel.close();
            outChannel.close();
            long end = System.currentTimeMillis();
            System.out.println("operate time: " + (end - start) + "ms");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inChannel != null) {
                    inChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    //慢，文件复制异常
    public static void m2() {
        FileChannel inChannel = null;
        FileChannel outChannel = null;
        try {

            RandomAccessFile rFile = new RandomAccessFile("D:\\setupbag\\eclipse-jee-lune.zip", "r");
//            RandomAccessFile rFile = new RandomAccessFile("F:\\开发软件安装包\\eclipse-jee-lune.zip", "r");
            RandomAccessFile wFile = new RandomAccessFile("D:\\setupbag\\eclipse-jee-lune3.zip", "rw");
            inChannel = rFile.getChannel();
            outChannel = wFile.getChannel();
            int position = 0;
            int index = 0;
            long start = System.currentTimeMillis();
            MappedByteBuffer read;
            while (position < inChannel.size()) {
                read = outChannel.map(FileChannel.MapMode.READ_WRITE, position, 1024);
                outChannel.write(read);
                position += read.limit();
            }
            long end = System.currentTimeMillis();
            System.out.println("operate time:" + (end - start) + "ms");

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (inChannel != null) {
                    inChannel.close();
                }
                if (outChannel != null) {
                    outChannel.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void unmap(final Object buffer) {
        AccessController.doPrivileged((PrivilegedAction) () -> {
            try {
                Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);
                getCleanerMethod.setAccessible(true);
                Cleaner cleaner = (Cleaner) getCleanerMethod.invoke(buffer, new Object[0]);
                cleaner.clean();
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
        });

    }
}
